//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CSprite9.cpp>
///	@path	~/src/graphics/dx9/
///	@date	2007/11/09
///	@desc	DirectX 9 sprite implementation.

#include "config/config.h"

#include "lib/math/matrix.h"
#include "lib/math/math_win32.h"
#include "lib/system/thread_debug.h"

#include "graphics/DxHelpers.h"
#include "graphics/dx9/CSprite9.h"
#include "graphics/dx9/CFont9.h"

namespace xeres {

	IMPL_IOBJECT_CLASS( CSprite9 );

	// ctor
	CSprite9::CSprite9( ID3DXSprite * sprite )
		: m_pSprite( sprite )
	{
	}

	// dtor
	CSprite9::~CSprite9( void )
	{
		if( m_pSprite )
		{
			UINT rest = m_pSprite->Release();
			if( rest != 0 )
			{
				TRACE_ERROR( _S("CSprite9::DTOR: Invalid ID3DXSprite reference count.") );
				FATAL_ABORT( _S("Invalid ID3DXSprite reference count.") );
			}
		}
	}

	// on lost device
	bool CSprite9::OnLostDevice( void )
	{
		TRACK_FUNCTION_SCOPE();
		RUNNING_ON_THREAD( _S("device") );

		if( m_pSprite )
		{
			HRESULT hr = m_pSprite->OnLostDevice();
			return SUCCEEDED( hr );
		}
		return true;
	}

	// on reset device
	bool CSprite9::OnResetDevice( RefWeak<IDevice> device )
	{
		TRACK_FUNCTION_SCOPE();
		RUNNING_ON_THREAD( _S("device") );

		if( m_pSprite )
		{
			HRESULT hr = m_pSprite->OnResetDevice();
			return SUCCEEDED( hr );
		}
		return true;
	}

	// draw text
	int CSprite9::DrawText( RefWeak<IFont> font , const WString& text ,
		int rect[4] , int style , PackColor4 color )
	{
		RefWeak<CFont9> font9 = font;
		return font9->DrawTextX( m_pSprite , text , rect , style , color.get_packed_argb() );
	}

	void CSprite9::Begin( RenderContext& rc )
	{
		m_pSprite->Begin( D3DXSPRITE_ALPHABLEND );
		
		Matrix<float> mat;
		mat.identity();

		m_pSprite->SetTransform( (D3DXMATRIX*)&mat );
	}

	void CSprite9::End( RenderContext& rc )
	{
		m_pSprite->End();
	}
	// DrawTexture
	void CSprite9::DrawTexture( RefWeak<ITexture> tex , const Rect<int> * rect , float depth )
	{
		IDirect3DTexture9 * texture = NULL;
		tex->GetTextureInterface()->QueryInterface( IID_IDirect3DTexture9 , (void**)&texture );
		if( texture == NULL )
		{
			TRACE_ERROR( _S("CSprite9::DrawTexture: Invalid texture class %s to draw.") , tex->GetClassName().c_str() );
			return;
		}

		Pair<int> size = tex->GetSize();
		int width = size.x;
		int height = size.y;

		// make destination rectangle
		RECT rc;
		RECT rt = { 0 , 0 , width , height };
		if( rect )
		{
			rc.left = rect->left();
			rc.top = rect->top();
			rc.right = rect->right();
			rc.bottom = rect->bottom();
		}
		else
		{
			rc.left = rc.top = 0;
			rc.right = width;
			rc.bottom = height;
		}

		float scale_x = (float)RectWidth( rc ) / (float)width;
		float scale_y = (float)RectHeight( rc ) / (float)height;

		// make transform
		D3DXMATRIXA16 matTransform;
		dx9::D3DXMatrixScaling( &matTransform , scale_x , scale_y , 1.0f );

		m_pSprite->SetTransform( &matTransform );

		D3DXVECTOR3 pos( (float)rc.left , (float)rc.top , depth );
		pos.x /= scale_x;
		pos.y /= scale_y;

		HRESULT hr = m_pSprite->Draw( texture , &rt , NULL , &pos , 0xffffffff );
		texture->Release();
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CSprite9::DrawTexture: Failed to draw texture: %s") ,
				d3d_get_err(hr) );
		}
	}

} // namespace xeres
